home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 2
/
Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso
/
Aminet
/
gfx
/
conv
/
ilbm24.lha
/
ilbm
/
writeilbm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-12
|
7KB
|
227 lines
/*
* Writeilbm.c
*
* Writes out a 24 bit IFF ILBM file, compressed or uncompressed from a 24 or 32 bit
* Sun Raster file.
* By Brett Van Sprewenburg
*
* A nice addition would be to convert regular 8 bit rasters to 24 bit, then write the ilbm.
* (see version 1.4, hehe)
*
* Credit to the ppm utilities, the developer(s) of xv, and Commodore-Amiga for
* code and ideas.
*
* Version
* 1.0 2/1/93 First working version, with hardcoded form and body chunk sizes.
* Only uncompressed images work.
* 1.1 2/2/93 Added in the correct form and body sizes with compression by altering
* the file after it was written.
*
* 1.2 2/4/93 First working version with compression done correctly. I still wouldn't
* be able to tell you exactly what was wrong. Fixed multiple things with
* readilbm integration. The biggest problem with this version is that it's sloooow.
* A faster way may be to do 8 planes at once, instead of a plane at a time.
* 1.3 2/9/93 Fixed previous slowness by compiling with acc -fast. ANIS'fied code also for
* compilation with acc without warnings.
* 1.4 2/10/93 Added reading and conversion of 8 bit rasters into 24 bit ilbms.
* 1.4.1 2/12/93 Checked that memeory allocations succeded.
* First public release.
*/
#include <writeilbm.h>
int WriteILBM(char *, int);
extern byte *pic; /* Pointer to pixel interleaved raster */
/* Or index into cmap if < 24 bit planes */
extern byte r[255],g[255],b[255]; /* Said cmap */
int WriteILBM(char *ilbmfile, int compression)
{
FILE *fp;
long formsize,bmhdsize,bodysize;
byte *coded_rowbuf,*cp,*raw_rowbuf;
int rel_count,rgbline,linesize,mask,yoffset,offset,push;
register int row, col, plane;
unsigned int bit;
static byte *image,*hpic,*ebitimage,*tpic;
int pad,tot_bytes,packedbytes,ycoffset,coffset,ccol = 0;
tot_bytes = packedbytes = 0;
if ((fp = fopen(ilbmfile,"w")) == NULL) {
fprintf(stderr,"Open of '%s' for writing failed.\n",ilbmfile);
return -1;
}
/* I'm fairly certain that I can't handle an odd sized bitmap, so I'll just turn 'em away */
if ((sunheader.ras_width % 8) != 0) {
fprintf(stderr,"Width of '%d' is not gonna work. Must be multiple of 8.\n",sunheader.ras_width);
fclose(fp);
return -1;
}
if (sunheader.ras_depth < 24) { /* Convert 8 to 24 bits */
if (sunheader.ras_maptype != RMT_EQUAL_RGB) {
fprintf(stderr,"Unknown colormap type. Save from 'xv' and try again.\n");
fclose(fp);
return -1;
}
tpic = pic;
fprintf(stderr,"Converting Sun Raster to 24 bit planes.\n");
hpic = (byte *)malloc(sunheader.ras_height * sunheader.ras_width * 3);
if (hpic == NULL) {
fprintf(stderr,"Can't get the memory I need...\n");
fclose(fp);
return -2;
}
ebitimage = hpic;
for (row = 0; row < (int)sunheader.ras_height; row++) {
yoffset = row * sunheader.ras_width;
ycoffset = row * (sunheader.ras_width * 3);
for (col = 0; col < (int)sunheader.ras_width; col++) {
offset = yoffset + col;
coffset = ycoffset + ccol;
*(hpic + coffset) = r[*(tpic + offset)];
coffset++;
*(hpic + coffset) = g[*(tpic + offset)];
coffset++;
*(hpic + coffset) = b[*(tpic + offset)];
ccol+=3;
if (ccol == (sunheader.ras_width * 3))
ccol = 0;
}
}
pic = ebitimage;
}
/* Assign information to ilbm header */
/* See AmigaDOS hardware RKM for more info */
ilbmheader.w = (unsigned short)sunheader.ras_width;
ilbmheader.h = (unsigned short)sunheader.ras_height;
ilbmheader.x = 0;
ilbmheader.y = 0;
ilbmheader.nPlanes = 24; /* We're only going to write 24 bit IFF's */
ilbmheader.masking = mskNone;
if (compression) {
ilbmheader.compression = cmpByteRun1;
printf("Compression On.\n");
} else
ilbmheader.compression = cmpNone;
ilbmheader.pad1 = 0;
ilbmheader.transparentColor = 0;
ilbmheader.xAspect = 10;
ilbmheader.yAspect = 10;
ilbmheader.pageWidth = (unsigned short)sunheader.ras_width ;
ilbmheader.pageHeight = (unsigned short)sunheader.ras_height;
/* Full pixel interleaved line consists of tuplets of rgb values */
rgbline = ilbmheader.w * 3;
coded_rowbuf = (byte *)malloc(ilbmheader.w);
raw_rowbuf = (byte *)malloc(rgbline);
if (coded_rowbuf == NULL || raw_rowbuf == NULL) {
fprintf(stderr,"Can't get the memory I need...\n");
fclose(fp);
return -2;
}
/* RoyBytes fromula from ilbm.h */
linesize = RowBytes(ilbmheader.w);
bmhdsize = sizeof(struct BitMapHeader);
if (!compression) {
bodysize = ilbmheader.h * linesize * ilbmheader.nPlanes;
formsize = 4 + 4 + 4 + bmhdsize + 4 + 4 + bodysize;
} else {
bodysize = 999999;
formsize = 999999; /* Do this because we don't know how much compression we'll get */
}
fwrite("FORM",4,1,fp);
fwrite(&formsize,4,1,fp);
fwrite("ILBM",4,1,fp);
fwrite("BMHD",4,1,fp);
fwrite(&bmhdsize,4,1,fp);
fwrite(&ilbmheader,bmhdsize,1,fp);
fwrite("BODY",4,1,fp);
fwrite(&bodysize,4,1,fp);
image = raw_rowbuf; /* Hold this pointer to the raw buffer in image pointer */
/* This next whole thing took quite a while to figure out
This file format looks like this: ( all data is bit reversed )
Plane data scanline
-------------------------------------------
Plane 0: RowBytes of red 0
Plane 1: RowBytes of red 0
|
Plane 7: RowBytes of red 0
Plane 8: RowBytes of green 0
|
Plane 15: RowBytes of green 0
Plane 16: RowBytes of blue 0
|
Plane 23: RowBytes of blue 0
Plane 0: RowBytes of red 1
Plane 1: RowBytes of red 1
and the beat goes on...
*/
/* Figure this next bit out for yourself :-< */
for (row = 0;row < (int)ilbmheader.h;row++) {
yoffset = row * rgbline;
raw_rowbuf = image;
for (plane = 0 ;plane < (int)ilbmheader.nPlanes; plane++) {
if (plane < 8) {
push = plane;
} else if (plane > 15) {
push = plane - 16;
}
else {
push = plane - 8;
}
mask = 1 << push; /* how many bits to push */
cp = coded_rowbuf;
*cp = 0;
for (col = (plane / 8), rel_count = 0 ; col < rgbline; rel_count++ ,col+=3) {
offset = yoffset + col;
bit = (*(pic + offset) & mask) ? 1 : 0;
*cp |= bit << ( 7 - (rel_count % 8) );
if ((rel_count % 8) == 7) { /* Every 8th byte, advance pixel */
cp++;
*cp = 0;
}
}
if (compression) { /* This bit is pretty obvious. */
raw_rowbuf = image; /* compression is rle, as specified in AmigaDOS 2.0 RKM */
packedbytes = packrow(coded_rowbuf, raw_rowbuf, linesize);
tot_bytes+=packedbytes;
fwrite(raw_rowbuf, packedbytes, 1, fp);
} else /* Write uncompressed data */
fwrite(coded_rowbuf, linesize, 1, fp);
}
}
if (compression) {
fclose(fp); /* close because we must alter the fopen flags */
if ((fp = fopen(ilbmfile,"r+")) == NULL) {
fprintf(stderr,"Open of '%s' for rewriting failed.\n",ilbmfile);
return -1; /* Hack in the real bodysize and formsize values */
}
formsize = tot_bytes + ILBMHSIZE;/* 40 is the number of bytes in the header after FORM and size */
fseek(fp,4L,0);
fwrite(&formsize,4,1,fp);
fseek(fp,44L,0);
fwrite(&tot_bytes,4,1,fp);
}
if ((tot_bytes % 2) != 0) { /* Pad the body chunk out to an even byte */
fseek(fp,0L,2);
pad = 0;
fwrite(&pad,1,1,fp);
}
fclose(fp);
free(coded_rowbuf);
free(raw_rowbuf);
return 0;
}